﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using DAL;
using DAL.Repositories;
using EntitiesLayer;
using System.Drawing;
using DAL.Repositorios;

namespace BLL
{
    
    public class GestorMantenimientoUsuarios
    {
        IRepository<Usuario> repo;

        public GestorMantenimientoUsuarios() {

            repo = UnitOfWork.UsuarioManRepository;
        }
        public IEnumerable<Usuario> ListarUsuarios() {

            return repo.GetAll();
        }
        public IEnumerable<Usuario> listarClientesConPlan() {

            return UnitOfWork.ClienteRepository.ClientesConsultarClientesConPlan();
        }

        public IEnumerable<Funcionario> ListarFuncionarios() 
        {
            return UnitOfWork.RepoEFuncionario.GetAll();
        }

        public IEnumerable<Cliente> ListarCliente() {

            return UnitOfWork.ClienteRepository.GetAll();
        }
        public Usuario consultarPorId(int id) {

            return repo.GetById(id);
        }

        
        public void registrarUsuario(string identificacion, string nombre, string PApellido,
           string SApellido, DateTime fechaNacimiento, DateTime fechaIngreso,
           Genero genero, Bitmap foto, string alias, string nombreUsuario,
           string discripcionTipoId, string nacionalidad, int idRol,
           string telefono, string correo, char tipoUsuario)
        {
             Usuario usuario;

             if (tipoUsuario == 'C')
                 usuario = new Cliente(
                     identificacion, nombre, PApellido,
                     SApellido, fechaNacimiento, fechaIngreso,
                     genero, foto, alias, nombreUsuario,
                     discripcionTipoId, nacionalidad, new Rol(idRol));
             else if (tipoUsuario == 'F')
                 usuario = new Funcionario(
                     identificacion, nombre, PApellido,
                     SApellido, fechaNacimiento, fechaIngreso,
                     genero, foto, alias, nombreUsuario,
                     discripcionTipoId, nacionalidad, new Rol(idRol));
             else
                 throw new ArgumentException("El tipo no es valido");
            
            repo.Insert(usuario);
            agregarInfoPostRegistrar(usuario,correo, telefono);

            
        }

        private void agregarInfoPostRegistrar(Usuario usuario,string correo, string telefono) {

            IRepository<CorreoElectronico> repoC= UnitOfWork.CorreoElectronicoRepository;
            IRepository<Telefono> repot= UnitOfWork.TelefonosUsuarios;
            
            

            repo.ActionAfterSave +=
                () =>
                {
                    int idUsuario = (int)repo.IdAutoGenerados[usuario];
                    //no deberia castiar cambiar todos los atributos y valores a long despues
                    repoC.Insert(new CorreoElectronico(idUsuario, correo));
                    repot.Insert(new Telefono(idUsuario, telefono));
                    repoC.Save();
                    repot.Save();
                };
        }


        public void ModificarUsuario(string identificacion, string nombre, string PApellido,
         string SApellido, DateTime fechaNacimiento, DateTime fechaIngreso,
         Genero genero, Bitmap foto, string alias, string nombreUsuario,
         string discripcionTipoId, string nacionalidad, int idRol,
         int idFuncionario, bool ClaveAuto, EstadoUsuario estado)
        {

            Usuario usuario= new Usuario(
                identificacion, nombre, PApellido,
            SApellido, fechaNacimiento, fechaIngreso,
            genero, foto, alias, nombreUsuario,
            discripcionTipoId, nacionalidad, new Rol(idRol),
            
            ClaveEsAuto: ClaveAuto, 
            idUsuario: idFuncionario,
            estado: estado
            
            );


            repo.Update(usuario);
            



        }

        public void ModificarUsuarioUltimoCT(string identificacion, string nombre, string PApellido,
        string SApellido, DateTime fechaNacimiento, DateTime fechaIngreso,
        Genero genero, Bitmap foto, string alias, string nombreUsuario,
        string discripcionTipoId, string nacionalidad, int idRol,
        int id, bool ClaveAuto, EstadoUsuario estado, 
            string correo, string telefono, TipoUsuario tipo) {


                Usuario usuario = UnitOfWork.UsuarioManRepository.GetById(id);
                  
                 usuario.Identificacion=identificacion;
                 usuario.Nombre= nombre;
                 usuario.PApellido= PApellido;
                 usuario.SApellido= SApellido;
                 usuario.FechaIngreso=fechaIngreso;
                 usuario.FechaNacimiento= fechaNacimiento;
                 usuario.Genero= genero;
                 usuario.Foto=foto;
                 usuario.Alias=alias;
                 usuario.NombreUsuario=nombreUsuario;
                 usuario.DiscripcionTipoId=discripcionTipoId;
                 usuario.Nacionalidad=nacionalidad;
                 usuario.Rol= new Rol(idRol);
                 usuario.ClaveEsAuto=ClaveAuto;
                 usuario.Estado=estado;
                 usuario.Tipo = tipo;

                repo.Update(usuario);

                repo.ActionAfterSave +=
                () =>
                {
                    ifNullInsert(

                        usuario.ListaTelefono,
                        UnitOfWork.TelefonosUsuarios,
                        (x) => x.Last().cambiarNumero(telefono),
                        () => new Telefono(id, telefono)
                    );

                    ifNullInsert(

                        usuario.ListaCorreo,
                        UnitOfWork.CorreoElectronicoRepository,
                        (x) => x.Last().cambiarCorreo(correo),
                        () => new CorreoElectronico(id, correo)
                    );

                };
        }

        public void ifNullInsert<T>(IList<T> lista, 
            IRepository<T> repo, 
            Func<IList<T>,T> modificar, 
            Func<T> registar){


              if (lista != null) 
              {
                  T cor = modificar(lista);
                  repo.Update(cor);
              }
              else
              {
                 repo.Insert(registar());
              }

              repo.Save();
        }

        public IList<Referencia> referenciasDeUsuario(int idUsuario) {
            Usuario u = repo.GetById(idUsuario);

            return u != null ? u.ListaReferencia : null;
        }

        public IEnumerable<Telefono> listarTelefonosReferencia( int idReferencia) {

            Referencia r = UnitOfWork.ReferenciasRepository.GetById(idReferencia);

            return r!=null? r.ListaTelefonos: null;
        }

        public void EliminarReferencia(Referencia referencia) {

            UnitOfWork.ReferenciasRepository.Delete(referencia);
            
        }
        public void EliminarTelefonoReferencia(Telefono telefono) {

            UnitOfWork.TelefonoReferenciaRepo.Delete(telefono);

        }
        public void RegistrarTelefonoDeReferencia(int idReferencia, string numero, string tipo) {

            UnitOfWork.TelefonoReferenciaRepo.Insert(new Telefono(idReferencia, numero, tipo));
            
        }
        public void EliminarUsuario(int idUsuario){

            Usuario usuario = repo.GetById(idUsuario);

            if(usuario!=null)
                repo.Delete(usuario);
        }
    
        public IList<Telefono> TelefonosDeUsuario(int idUsuario){

            Usuario u = UnitOfWork.UsuarioManRepository.GetById(idUsuario);

            return u != null ? u.ListaTelefono : null;
        ;
        
        }

        public void registrarTelefono(int idEntidadRelacionada, string numeroTelefono, string tipo)
        {

            Telefono tel = new Telefono(idEntidadRelacionada, numeroTelefono, tipo);

            UnitOfWork.TelefonosUsuarios.Insert(tel);

            
        
        }

        public void RegistrarCorreoUsuario(int idUsuario, string stringcorreo, string tipo, int idCorreo = 0)
        {
            CorreoElectronico correo = new CorreoElectronico(idUsuario, stringcorreo, tipo);

            UnitOfWork.CorreoElectronicoRepository.Insert(correo);
        }

        public void RegistrarReferenciaUsuario(int idUsuario, string nombre, string telefono)
        {

            Referencia referencia = new Referencia(idUsuario,nombre);

            UnitOfWork.ReferenciasRepository.Insert(referencia);
            UnitOfWork.ReferenciasRepository.ActionAfterSave += 
                () =>
                {
                    int idReferencia = (int)UnitOfWork.ReferenciasRepository.IdAutoGenerados[referencia];
                    UnitOfWork.TelefonoReferenciaRepo.Insert(new Telefono(idReferencia, telefono));
                };




        }

        public void EliminarReferencia(int id) {

            IRepository<Referencia> r = UnitOfWork.ReferenciasRepository;
            
            Referencia referencia = r.GetById(id);

            if(referencia!=null)
                r.Delete(referencia);
           
            //Mensa
        }

        public void EliminarTelefonoU(int idTelefono) {

            UnitOfWork.TelefonosUsuarios.Delete(new Telefono(idTelefono));
            
        }

        public void EliminarCorreoU(CorreoElectronico correo)
        {
            UnitOfWork.CorreoElectronicoRepository.Delete(correo);
            
        }

        public IEnumerable<Rol> ListarRoles()
        {

            return UnitOfWork.RolRepository.GetAll();

        }

        public IEnumerable<CorreoElectronico> CorreosDeUsuario( int idUsuario) { 
        
            Usuario u = UnitOfWork.UsuarioManRepository.GetById(idUsuario);

            return u != null ? u.ListaCorreo : null;
        
        }

        public void RegistrarHorario(int idFuncionario, DiasSemana dia, TimeSpan horaDeEntrada, TimeSpan horaDeSalida) {

            HorarioDia h = new HorarioDia(idFuncionario, dia, horaDeEntrada, horaDeSalida);

            UnitOfWork.RepoHoraiosFuncionario.Insert(h);
            
            
        }

        public void EliminarHorario(HorarioDia horario){
            
            UnitOfWork.RepoHoraiosFuncionario.Delete(horario);

            
        }

        public IEnumerable<HorarioDia> ListarHorariosDeFuncionario(int idFuncionario) {

            Funcionario funcionario = UnitOfWork.RepoEFuncionario.GetById(idFuncionario);

            return funcionario != null ? funcionario.HorariosDeTrabajo : null;
        }

        public void guadarCambiosUsuario() {

            repo.Save();
        }

        public void guadarCambiosTelefono() {

            UnitOfWork.TelefonosUsuarios.Save();
        }

        public void guardarCambiosCorreo() {

            UnitOfWork.CorreoElectronicoRepository.Save();
        }

        public void guardarCambioReferencia() {

            UnitOfWork.ReferenciasRepository.Save();
            UnitOfWork.TelefonoReferenciaRepo.Save();

        }

        public void guardarCambiosHorarios() {

            UnitOfWork.RepoHoraiosFuncionario.Save();
        
        }

      

       

       
    
    }

   
}
